# 支持汇编指令
from cpu import pin

# 需要执行的指令集合，取指令集合
FETCH = [
    pin.PC_OUT | pin.MAR_IN,
    pin.RAM_OUT | pin.IR_IN | pin.PC_INC,
    pin.PC_OUT | pin.MAR_IN,
    pin.RAM_OUT | pin.DST_IN | pin.PC_INC,
    pin.PC_OUT | pin.MAR_IN,
    pin.RAM_OUT | pin.SRC_IN | pin.PC_INC,
]

# 指令定义
# 2地址指令
MOV = (0 << pin.ADDR2_SHIFT) | pin.ADDR2
ADD = (1 << pin.ADDR2_SHIFT) | pin.ADDR2
SUB = (2 << pin.ADDR2_SHIFT) | pin.ADDR2
CMP = (3 << pin.ADDR2_SHIFT) | pin.ADDR2

AND = (4 << pin.ADDR2_SHIFT) | pin.ADDR2
OR = (5 << pin.ADDR2_SHIFT) | pin.ADDR2
XOR = (6 << pin.ADDR2_SHIFT) | pin.ADDR2


# 1地址指令
INC = (0 << pin.ADDR1_SHIFT) | pin.ADDR1
DEC = (1 << pin.ADDR1_SHIFT) | pin.ADDR1
NOT = (2 << pin.ADDR1_SHIFT) | pin.ADDR1
JMP = (3 << pin.ADDR1_SHIFT) | pin.ADDR1

# 6大条件跳转，根据PSW来判定
# 溢出跳转
JO = (4 << pin.ADDR1_SHIFT) | pin.ADDR1
# 非溢出跳转
JNO = (5 << pin.ADDR1_SHIFT) | pin.ADDR1
# 零跳转
JZ = (6 << pin.ADDR1_SHIFT) | pin.ADDR1
# 非零跳转
JNZ = (7 << pin.ADDR1_SHIFT) | pin.ADDR1
# 奇数跳转
JP = (8 << pin.ADDR1_SHIFT) | pin.ADDR1
# 非奇数跳转
JNP = (9 << pin.ADDR1_SHIFT) | pin.ADDR1

# 堆栈指令
PUSH = (10 << pin.ADDR1_SHIFT) | pin.ADDR1
POP = (11 << pin.ADDR1_SHIFT) | pin.ADDR1
# 函数调用
CALL = (12 << pin.ADDR1_SHIFT) | pin.ADDR1
# 中断
INT = (12 << pin.ADDR1_SHIFT) | pin.ADDR1

# 0地址指令
NOP = 0
# 函数返回
RET = 1
# 中断返回
IRET = 2
#
STI = 3

CLI = 4
# 0011 1111
HLT = 0x3f

# 支持的指令
INS_SUPPORT_LIST = {
    2: {
         # 这个地方不能用'MOV'字符串的key
         MOV: {
             # 1. MOV A,5;
             (pin.AM_REG, pin.AM_INS): [
                 pin.DST_W | pin.SRC_OUT,
             ],
             # 2. MOV A,B;
             (pin.AM_REG, pin.AM_REG): [
                 pin.DST_W | pin.SRC_R
             ],
             # 3. MOV A,[5] or [0x12]
             (pin.AM_REG, pin.AM_DIR): [
                 pin.SRC_OUT | pin.MAR_IN,
                 pin.RAM_OUT | pin.DST_W
             ],
             # 4. MOV A,[B]
             (pin.AM_REG, pin.AM_RAM): [
                 pin.SRC_R | pin.MAR_IN,
                 pin.RAM_OUT | pin.DST_W
             ],
             # 5. MOV [5],5 or MOV [0x12],12
             (pin.AM_DIR, pin.AM_INS): [
                 pin.DST_OUT | pin.MAR_IN,
                 pin.RAM_IN | pin.SRC_OUT
             ],
             # 6. MOV [5],A;
             (pin.AM_DIR, pin.AM_REG): [
                 pin.DST_OUT | pin.MAR_IN,
                 pin.RAM_IN | pin.SRC_R
             ],
             # 7. MOV [5],[6]
             (pin.AM_DIR, pin.AM_DIR): [
                 pin.SRC_OUT | pin.MAR_IN,
                 pin.T1_IN | pin.RAM_OUT,
                 pin.DST_OUT | pin.MAR_IN,
                 pin.RAM_IN | pin.T1_OUT
             ],
             # 8. MOV [5],[A]
             (pin.AM_DIR, pin.AM_RAM): [
                 pin.SRC_R | pin.MAR_IN,
                 pin.T1_IN | pin.RAM_OUT,
                 pin.DST_OUT | pin.MAR_IN,
                 pin.RAM_IN | pin.T1_OUT
             ],
             # 9. MOV [A],5;
             (pin.AM_RAM, pin.AM_INS): [
                 pin.DST_R | pin.MAR_IN,
                 pin.RAM_IN | pin.SRC_OUT
             ],
             # 10. MOV [A],B;
             (pin.AM_RAM, pin.AM_REG): [
                 pin.DST_R | pin.MAR_IN,
                 pin.RAM_IN | pin.SRC_R
             ],
             # 11. MOV [A],[5]
             (pin.AM_RAM, pin.AM_DIR): [
                 pin.SRC_OUT | pin.MAR_IN,
                 pin.RAM_OUT | pin.T2_IN,
                 pin.DST_R | pin.MAR_IN,
                 pin.RAM_IN | pin.T2_OUT
             ],
             # 12. MOV [A],[B]
             (pin.AM_RAM, pin.AM_RAM): [
                 pin.SRC_R | pin.MAR_IN,
                 pin.RAM_OUT | pin.T2_IN,
                 pin.DST_R | pin.MAR_IN,
                 pin.RAM_IN | pin.T2_OUT
             ]
         },
         ADD: {
             # 1. ADD A,5;
             (pin.AM_REG, pin.AM_INS): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_OUT | pin.B_IN,
                 pin.OP_ADD | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ],
             # 2. ADD A,B;
             (pin.AM_REG, pin.AM_REG): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_R | pin.B_IN,
                 pin.OP_ADD | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ]
         },
         SUB: {
             # 1. SUB A,5;
             (pin.AM_REG, pin.AM_INS): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_OUT | pin.B_IN,
                 pin.OP_SUB | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ],
             # 2. SUB A,B;
             (pin.AM_REG, pin.AM_REG): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_R | pin.B_IN,
                 pin.OP_SUB | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ]
         },
         CMP: {
             # 1. CMP A,5;
             (pin.AM_REG, pin.AM_INS): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_OUT | pin.B_IN,
                 pin.OP_SUB | pin.ALU_PSW
             ],
             # 2. CMP A,B;
             (pin.AM_REG, pin.AM_REG): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_R | pin.B_IN,
                 pin.OP_SUB | pin.ALU_PSW
             ]
         },
         AND: {
             # 1. AND A,5;
             (pin.AM_REG, pin.AM_INS): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_OUT | pin.B_IN,
                 pin.OP_AND | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ],
             # 2. AND A,B;
             (pin.AM_REG, pin.AM_REG): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_R | pin.B_IN,
                 pin.OP_AND | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ]
         },
         OR: {
             # 1. OR A,5;
             (pin.AM_REG, pin.AM_INS): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_OUT | pin.B_IN,
                 pin.OP_OR | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ],
             # 2. OR A,B;
             (pin.AM_REG, pin.AM_REG): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_R | pin.B_IN,
                 pin.OP_OR | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ]
         },
         XOR: {
             # 1. XOR A,5;
             (pin.AM_REG, pin.AM_INS): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_OUT | pin.B_IN,
                 pin.OP_XOR | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ],
             # 2. XOR A,B;
             (pin.AM_REG, pin.AM_REG): [
                 pin.DST_R | pin.A_IN,
                 pin.SRC_R | pin.B_IN,
                 pin.OP_XOR | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
             ]
         }
    },
    1: {
        INC: {
            # INC A
            pin.AM_REG: [
                pin.DST_R | pin.A_IN,
                pin.OP_INC | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
            ]
        },
        DEC: {
            # DEC A
            pin.AM_REG: [
                pin.DST_R | pin.A_IN,
                pin.OP_DEC | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
            ]
        },
        NOT: {
            # NOT A
            pin.AM_REG: [
                pin.DST_R | pin.A_IN,
                pin.OP_NOT | pin.ALU_PSW | pin.DST_W | pin.ALU_OUT
            ]
        },
        JMP: {
            # JMP aaaa;
            pin.AM_INS: [
                pin.DST_OUT | pin.PC_IN
            ],
        },
        JO: {
            pin.AM_INS: [
                pin.DST_OUT | pin.PC_IN
            ],
        },
        JNO: {
            pin.AM_INS: [
                pin.DST_OUT | pin.PC_IN
            ],
        },
        JZ: {
            pin.AM_INS: [
                pin.DST_OUT | pin.PC_IN
            ],
        },
        JNZ: {
            pin.AM_INS: [
                pin.DST_OUT | pin.PC_IN
            ],
        },
        JP: {
            pin.AM_INS: [
                pin.DST_OUT | pin.PC_IN
            ],
        },
        JNP: {
            pin.AM_INS: [
                pin.DST_OUT | pin.PC_IN
            ],
        },
        PUSH: {
            # push 1，
            pin.AM_INS: [
                # 栈指针减1
                pin.SP_OUT | pin.A_IN,
                pin.OP_DEC | pin.SP_IN | pin.ALU_OUT,
                # 减一后的指针放到内存地址的低位
                pin.SP_OUT | pin.MAR_IN,
                # 堆栈的段指针放到内存地址的高位
                pin.SS_OUT | pin.MSR_IN,
                # 目标数写入到内存
                pin.DST_OUT | pin.RAM_IN,
                # 代码段0写到内存地址高位，表示切换到代码段执行
                pin.CS_OUT | pin.MSR_IN,
            ],
            pin.AM_REG: [
                pin.SP_OUT | pin.A_IN,
                pin.OP_DEC | pin.SP_IN | pin.ALU_OUT,
                pin.SP_OUT | pin.MAR_IN,
                pin.SS_OUT | pin.MSR_IN,
                # 寄存器寻址和立即数区别，在于立即数是直接输出数据到总线，而寄存器寻址是读取寄存器内值输出到总线
                pin.DST_R | pin.RAM_IN,
                # 代码段0写到内存地址高位，表示切换到代码段执行
                pin.CS_OUT | pin.MSR_IN,
            ],
        },
        POP: {
            pin.AM_REG: [
                # 栈指针指向内存地址地位
                pin.SP_OUT | pin.MAR_IN,
                # 栈段指向内存地址高位
                pin.SS_OUT | pin.MSR_IN,
                # 将内存栈顶的值读取到目标寄存器
                pin.DST_W | pin.RAM_OUT,
                # 将栈指针加一
                pin.SP_OUT | pin.A_IN,
                pin.OP_INC | pin.SP_IN | pin.ALU_OUT,
                # 代码段0写到内存地址高位，表示切换到代码段执行
                pin.CS_OUT | pin.MSR_IN,
            ],
        },
        CALL: {
            # call show
            pin.AM_INS: [
                # 栈指针减1
                pin.SP_OUT | pin.A_IN,
                pin.OP_DEC | pin.SP_IN | pin.ALU_OUT,
                # 减一后的指针放到内存地址的低位
                pin.SP_OUT | pin.MAR_IN,
                # 栈段指针放到内存地址的高位
                pin.SS_OUT | pin.MSR_IN,
                # pc写入到内存栈中，保存起来
                pin.PC_OUT | pin.RAM_IN,
                # 将目标指令行写入到pc，准备执行
                pin.DST_OUT | pin.PC_IN,
                # 代码段0写到内存地址高位，表示切换到代码段执行
                pin.CS_OUT | pin.MSR_IN,
            ]
        },
        INT: {
            # int show 中断调用
            pin.AM_INS: [
                # 栈指针减1
                pin.SP_OUT | pin.A_IN,
                pin.OP_DEC | pin.SP_IN | pin.ALU_OUT,
                # 减一后的指针放到内存地址的低位
                pin.SP_OUT | pin.MAR_IN,
                # 栈段指针放到内存地址的高位
                pin.SS_OUT | pin.MSR_IN,
                # pc写入到内存栈中，保存起来
                pin.PC_OUT | pin.RAM_IN,
                # 将目标指令行写入到pc，准备执行
                pin.DST_OUT | pin.PC_IN,
                # 代码段0写到内存地址高位，表示切换到代码段执行。并且关闭中断位写入PSW
                pin.CS_OUT | pin.MSR_IN | pin.ALU_PSW | pin.ALU_CLI,
            ]
        },
    },
    0: {
        NOP: [
            pin.CYC
        ],
        RET: [
            # 栈指针指向内存地址地位
            pin.SP_OUT | pin.MAR_IN,
            # 栈段指向内存地址高位
            pin.SS_OUT | pin.MSR_IN,
            # 将内存栈顶的值读取到PC
            pin.PC_IN | pin.RAM_OUT,
            # 将栈指针加一
            pin.SP_OUT | pin.A_IN,
            pin.OP_INC | pin.SP_IN | pin.ALU_OUT,
            # 代码段0写到内存地址高位，表示切换到代码段执行
            pin.CS_OUT | pin.MSR_IN,
        ],
        IRET: [
            # 栈指针指向内存地址地位
            pin.SP_OUT | pin.MAR_IN,
            # 栈段指向内存地址高位
            pin.SS_OUT | pin.MSR_IN,
            # 将内存栈顶的值读取到PC
            pin.PC_IN | pin.RAM_OUT,
            # 将栈指针加一
            pin.SP_OUT | pin.A_IN,
            pin.OP_INC | pin.SP_IN | pin.ALU_OUT,
            # 代码段0写到内存地址高位，表示切换到代码段执行。并且允许中断并写入PSW
            pin.CS_OUT | pin.MSR_IN | pin.ALU_PSW | pin.ALU_STI,
        ],
        STI: [
            pin.ALU_PSW | pin.ALU_STI
        ],
        CLI: [
            pin.ALU_PSW | pin.ALU_CLI
        ],
        HLT: [
            pin.HLT
        ]
    }
}
